/**
 * Copyright (c) 2012-2014, Yang Yang <cntototo@gmail.com>
 *
 * This software may be distributed under the terms of the New BSD License.
 * See README for more details.
 */

#ifndef DEF_H
#define DEF_H

#include <stdint.h>

typedef uint8_t  u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

typedef int8_t   s8;
typedef int16_t  s16;
typedef int32_t  s32;
typedef int64_t  s64;

typedef u16 be16;
typedef u16 le16;
typedef u32 be32;
typedef u32 le32;
typedef u64 be64;
typedef u64 le64;

#ifdef __GNUC__
#define STRUCT_PACKED __attribute__ ((packed))
#else
#define STRUCT_PACKED
#endif

/** Interface name length */
#ifndef IFNAMSIZ
#define IFNAMSIZ 16
#endif

/** MAC address bytes */
#ifndef ETH_ALEN
#define ETH_ALEN 6
#endif

/** UUID length */
#define UUID_LEN 16

/** Max SSID length */
#define MAX_SSID_LEN 32

/** Small buffer length */
#define SMALL_BUF_LEN 512
/** Buffer length */
#define BUF_LEN 2048
/** Large buffer length */
#define LARGE_BUF_LEN 4096

/** Event buffer length */
#define EVT_BUF_LEN BUF_LEN

/** Min passphrase length */
#define MIN_PASSPHRASE_LEN 8
/** Max passphrase length */
#define MAX_PASSPHRASE_LEN 63

/** PSK length in byte */
#define PSK_BYTE_LEN 32

/** Maximum number of devices to scan */
#define MAX_SCAN_DEVICES 16

/** MAC printf format */
#define MACSTR "%02hhX:%02hhX:%02hhX:%02hhX:%02hhX:%02hhX"
/** MAC printf argument */
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
/** MAC scanf argument */
#define MAC2SCAN(a) &(a)[0], &(a)[1], &(a)[2], &(a)[3], &(a)[4], &(a)[5]

#define TRUE  1
#define FALSE 0

#define SUCCESS 0
#define FAIL    1

#ifndef BIT
#define BIT(x) (1 << (x))
#endif

/**
 * enum wfs_internal_err -- WFS internal error type
 *
 * WFS_INTERNAL_ERR_SUCCESS: The operation succeeds.
 * WFS_INTERNAL_ERR_INVAL: The input info is invalid.
 * WFS_INTERNAL_ERR_OOM: Out of memory.
 * WFS_INTERNAL_ERR_OS: Failure in OS, such as TCP/IP socket failure.
 * WFS_INTERNAL_ERR_BUSY: WFS is too busy to perform the operation.
 * WFS_INTERNAL_ERR_NOTSUPP: The behavior is not supported at current status.
 * WFS_INTERNAL_ERR_NOENT: No entry in returned result.
 */
enum wfs_internal_err {
	WFS_INTERNAL_ERR_SUCCESS = 0,
	WFS_INTERNAL_ERR_INVAL,
	WFS_INTERNAL_ERR_OOM,
	WFS_INTERNAL_ERR_OS,
	WFS_INTERNAL_ERR_BUSY,
	WFS_INTERNAL_ERR_NOTSUPP,
	WFS_INTERNAL_ERR_NOENT
};

/**
 * enum wfs_security_protocol -- Security protocol type
 */
enum wfs_security_protocol {
	SEC_PROTO_WPA  = BIT(0),
	SEC_PROTO_RSN  = BIT(1),
	SEC_PROTO_WAPI = BIT(2)
};

/**
 * enum wfs_auth_alg -- Authentication algorithm
 */
enum wfs_auth_alg {
	AUTH_ALG_OPEN   = BIT(0),
	AUTH_ALG_SHARED = BIT(1),
	AUTH_ALG_LEAP   = BIT(2),
	AUTH_ALG_FT     = BIT(3),
	AUTH_ALG_SAE    = BIT(4)
};

/**
 * enum wfs_cipher -- Cipher type
 */
enum wfs_cipher {
	CIPHER_NONE         = 0,
	CIPHER_WEP40        = BIT(0),
	CIPHER_WEP104       = BIT(1),
	CIPHER_TKIP         = BIT(2),
	CIPHER_CCMP         = BIT(3),
	CIPHER_AES_128_CMAC = BIT(4),
	CIPHER_GCMP         = BIT(5),
	CIPHER_SMS4         = BIT(6),
	CIPHER_GCMP_256     = BIT(7),
	CIPHER_CCMP_256     = BIT(8),
	CIPHER_BIP_GMAC_128 = BIT(9),
	CIPHER_BIP_GMAC_256 = BIT(10),
	CIPHER_BIP_CMAC_256 = BIT(11),
	CIPHER_IGTK         = BIT(12),
	CIPHER_KRK          = BIT(13)
};

/**
 * enum wfs_key_mgmt -- Key management type
 */
enum wfs_key_mgmt {
	KEY_MGMT_NONE             = 0,
	KEY_MGMT_IEEE8021X        = BIT(0),
	KEY_MGMT_PSK              = BIT(1),
	KEY_MGMT_IEEE8021X_NO_WPA = BIT(2),
	KEY_MGMT_WPA_NONE         = BIT(3),
	KEY_MGMT_IEEE8021X_FT     = BIT(4),
	KEY_MGMT_PSK_FT           = BIT(5),
	KEY_MGMT_IEEE8021X_SHA256 = BIT(6),
	KEY_MGMT_PSK_SHA256       = BIT(7),
	KEY_MGMT_WSC              = BIT(8),
	KEY_MGMT_SAE              = BIT(9),
	KEY_MGMT_SAE_FT           = BIT(10),
	KEY_MGMT_WAPI_PSK         = BIT(11),
	KEY_MGMT_WAPI_CERT        = BIT(12),
	KEY_MGMT_CCKM             = BIT(13)
};

/**
 * enum mfp_options -- Management frame protection (IEEE 802.11w) options
 */
enum wfs_mfp_options {
	NO_MGMT_FRAME_PROTECTION = 0,
	MGMT_FRAME_PROTECTION_OPTIONAL = 1,
	MGMT_FRAME_PROTECTION_REQUIRED = 2
};

/**
 * enum wfs_ch_width -- Channel width
 */
enum wfs_ch_width {
	CH_WIDTH_UNKNOWN = 0,
	/** 5 MHz OFDM channel */
	CH_WIDTH_5,
	/** 10 MHz OFDM channel */
	CH_WIDTH_10,
	/** 20 MHz non-HT channel */
	CH_WIDTH_20_NOHT,
	/** 20 MHz HT channel */
	CH_WIDTH_20,
	/** 40 MHz channel */
	CH_WIDTH_40,
	/** 80 MHz channel */
	CH_WIDTH_80,
	/** 80+80 MHz channel */
	CH_WIDTH_80P80,
	/** 160 MHz channel */
	CH_WIDTH_160
};

/**
 * enum wfs_tdls_oper -- TDLS operation
 */
enum wfs_tdls_oper {
	/** Unknown operation */
	TDLS_UNKNOWN = 0,
	/** TDLS discovery request */
	TDLS_DISC_REQ,
	/** TDLS setup link */
	TDLS_SETUP,
	/** TDLS teardown link */
	TDLS_TEARDOWN,
	/** Enable TDLS link */
	TDLS_ENABLE_LINK,
	/** Disable TDLS link */
	TDLS_DISABLE_LINK
};

/**
 * struct wfs_cmd -- Command structure
 *
 * This structure is constructed by WFS daemon and sent to dispatcher.
 * Dispatcher re-send it to corresponding functionality.
 */
#define PARAM_MAX_NUM 10
struct wfs_cmd {
	char *cmd;
	char *params[PARAM_MAX_NUM];
	int   param_num;
	char str[SMALL_BUF_LEN];
};

#define OK_STR   "OK"
#define FAIL_STR "FAIL"

#define KEY_VALUE_DELIM '='
#define PARAM_DELIM " "
#define FREQ_DELIM ","

/** CMD, LEN, USG of each commands */
#define CMD(X) CMD_##X
#define LEN(X) strlen(CMD(X))
#define USG(X) USG_##X

/** ASSOCIATE */
#define CMD_ASSOCIATE "ASSOCIATE"
#define USG_ASSOCIATE "ASSOCIATE [bssid=XX:XX:XX:XX:XX:XX] [ssid=<num of chars>\"<SSID>\"] [passwd=<num of chars>\"<password>\"]"
/** REGISTER_IF */
#define CMD_REGISTER_IF "REGISTER_IF"
#define USG_REGISTER_IF "REGISTER_IF ifname=<ifname>"
/** SCAN */
#define CMD_SCAN "SCAN"
#define USG_SCAN "SCAN"
/** SCAN_RESULTS */
#define CMD_SCAN_RESULTS "SCAN_RESULTS"
#define USG_SCAN_RESULTS "SCAN_RESULTS"
/** STATUS */
#define CMD_STATUS "STATUS"
#define USG_STATUS "STATUS"
/** UNREGISTER_IF */
#define CMD_UNREGISTER_IF "UNREGISTER_IF"
#define USG_UNREGISTER_IF "UNREGISTER_IF ifname=<ifname>"
/** USE_DRIVER */
#define CMD_USE_DRIVER "USE_DRIVER"
#define USG_USE_DRIVER "USE_DRIVER driver=<driver>"

#define IS_CMD(cmd, X) (strlen((cmd)) == strlen(CMD(X)) && \
	strncmp((cmd), CMD(X), LEN(X)) == 0)

#endif /* DEF_H */
